/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * Licensed under Simplified BSD License
 *
 * Need override anything related to orientation
 * @author: jin Chen 
 * @date: Jun 9, 2005$
 * @version: 1.0
 */
package edu.psu.geovista.app.hce.dendroview.node;

import edu.psu.geovista.app.hce.clustering.model.LCluster;
import epoviz.trex.common.text.JTextUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HorizontalBNode extends VerticalBNode{
    private static final Logger logger=Logger.getLogger(HorizontalBNode.class.getName());

    /*******************************************************************************************************
     *                must override
     *******************************************************************************************************/


    protected Point[] getLocations(Point foot1,Point foot2,int distance){
        Point[] locs=new Point[5];
         int x=this.getLocation(distance, this.getOrient(), this.getGraphBound());//graphBound.width -distance;//
         int y=(foot1.y+foot2.y)/2;//;distance;//(int) (plotsize.height*(1- distance));
            Point myloc=new Point();
            myloc.setLocation(x,y); // 

            Point shoulder1=new Point();
            Point shoulder2=new Point();
            shoulder1.setLocation(x, foot1.y);
            shoulder2.setLocation(x, foot2.y);

           // locs[0]=myloc;
        locs=new Point[]{foot1,shoulder1,myloc,shoulder2,foot2};
        if(true ){
            System.out.println("");
            System.out.println("    A node locations(foot,shoulder, center, shoulder,foot:");
            //System.out.println("        ");
            for (int i=0;i<locs.length ;i++){
                System.out.println("        ["+locs[i].x +","+locs[i].y+"]");
            }
            Rectangle gb = this.getGraphBound();
            System.out.println("graph bound:"+gb+"\n");
        }
        return locs;
    }



    protected  int getLocation(int distance, int orient, Rectangle graphBound) {
        if(graphBound==null){
            logger.warning("Unable to deal with null graphBound");
            return 0;
        }
        int x =distance;//(int) (plotsize.height*(1- distance));
        if(orient == SwingConstants.EAST ){
            x =graphBound.x+distance;
        }
        else if (orient ==SwingConstants.WEST ){
             x =graphBound.x+graphBound.width -distance;
        }
        else{
            logger.severe("Unsupport oritation!");
        }
        return x;
    }
    protected boolean isOrientKnown(int orient){
         if(orient == SwingConstants.EAST ||orient ==SwingConstants.WEST ){
            return true;
        }
        return false;
    }
     public   Point getLeafLocation(int leafIndex) {

        if(this.leafsInterval==null){ //no external interval given, need use self compute value
            List<Point> locs = this.getLeafsLocation();
            if(locs==null)return null;
            return locs.get(leafIndex);
        }
        else{
             //int similarity=1;// leaf node similairty =0;
            double sim = getSimilarityForLeaf();
            int distance=this.getDistance(sim);
            int x=this.getLocation(distance, this.getOrient(), this.getGraphBound());
             //int x=this.getDistance(this.getMaxSimilarity() );
             int y=(int) this.leafsInterval[leafIndex];
             return new Point(x,y);
        }
     }
     protected void computeDefaultLeafsLocation(){

         if(logger.isLoggable(Level.FINE ) ){
             System.out.println("computeLeafsLocation() -->\n");
        }
        if(this.getGraphBound() ==null){
             if(logger.isLoggable(Level.FINE ) ){
                 System.out.println("  Graph bound is null, unable to calculate, simply return.");
             }
             //logger.fine("  Graph bound is null, unable to calculate, simply return.");
             return;
         }


        int x,y;



        //int similarity=1;// leaf node similairty =1;
       int distance=this.getDistance(getSimilarityForLeaf());//graphBound.height+this.offset.height ;   // 
       //  int distance=this.getDistance(this.getMaxSimilarity() );//for leaf
        if(logger.isLoggable(Level.FINE ) ){
                     System.out.println("   distance for leaf "+distance);
        }
        Rectangle bd = this.getGraphBound();
        double length = bd.height ;
        int numOfLeaf = this.getNumOfLeaf();
        int nodesize=(int) (length/numOfLeaf);
         if(logger.isLoggable(Level.FINE ) ){
                     System.out.println("   nodesize=" + nodesize+"\n");
          }

        java.util.List<Point> leafsloc=new ArrayList<Point>(numOfLeaf);
         if(logger.isLoggable(Level.FINE ) ){
                     System.out.println("   leaf location: -->\n");
             //System.out.println("       ");
          }

        for (int leafIndex =0;leafIndex <this.getNumOfLeaf();leafIndex++){

            //y=distance;
            x=this.getLocation(distance, this.getOrient(), this.getGraphBound());
            y= (int) (leafIndex *nodesize+nodesize/2f);// 
            Point loc = new Point(x, y);
            leafsloc.add(loc);
             if(logger.isLoggable(Level.FINE ) ){
                         System.out.println("       "+loc+ " , ");
              }

        }
        if(logger.isLoggable(Level.FINE ) ){
                     System.out.println("   leaf location: <--\n");

          }

         if(logger.isLoggable(Level.FINE ) ){
                     System.out.println("computeLeafsLocation() <--\n");

          }
         this.setLeafsLocation(leafsloc) ;


    }

     protected Point getLabelLocation( LCluster lf,String msg,Graphics2D g2d){
         int leafIndex = lf.getLfindex();
         Point lflocation = getLeafLocation(leafIndex);
         Rectangle2D textBound = JTextUtils.getTextBound(msg, this.labelfond, g2d);
         int x=0;
         int y=0;
         if(this.getOrient() ==SwingConstants.EAST ){
             x=(int) lflocation.x+5;
             y=(int) (lflocation.y+textBound.getHeight()/2);
         }
         else if(this.getOrient() ==SwingConstants.WEST ){
             x=(int) ((int) lflocation.x-textBound.getWidth() -5);
             y=(int) (lflocation.y+textBound.getHeight()/2);
         }
         else{
            logger.warning("Unsupport orient!"); 
         }
        return new Point(x,y);
    }

     protected  int getFullDistance() {
         if(graphBound==null) return 100;
         return graphBound.width-getSpaceForLabel() ;
    }
      public  double getSimilarity ( Point pt){
        Rectangle bd = this.getGraphBound();
        int x=pt.x -bd.x;
        int y=pt.y-bd.y;

       // double minsim = this.getMinSimilarity();
        int mindistance =0 ;//distance of minsim to minsim.this.getDistance(minsim);
        int minsimLoc = this.getLocation(mindistance, this.getOrient(), this.getGraphBound());
        int distance=Math.abs(pt.x-minsimLoc);//this is not good since if it pass the distance=0 point, it will show positive value again
        if(this.getOrient() ==SwingConstants.EAST ){
           distance=pt.x-minsimLoc;
         }
         else if(this.getOrient() ==SwingConstants.WEST ){
           distance=minsimLoc-pt.x;
         }

        return this.getSimilarity(distance);

    }


}
